local Config = require("Config")
local pi = math.acos(-1)
local sqrt2 = math.sqrt(2)
local os	= _G.os
local math  = _G.math
local floor = math.floor
local cos	= math.cos
local sin	= math.sin
local atan2	= math.atan2

function getTableCount(s)
	local count = 0
	if s == nil then return count end
	for _ in pairs(s) do
		count = count + 1
	end
	return count
end

function copyTableSimple(s, t, noNewTB)
	for k, v in pairs(s) do
		if type(v) == "table" then
			if not noNewTB then
				t[k] = {}
			end
			copyTableSimple(v, t[k])
		else
			t[k] = v
		end
	end
end

function copyTable(s)
	if not s then return end		
	local t = {}
	copyTableSimple(s,t)
	return t
end

function initTable(tb)
	if not tb then return end	
	for k in pairs(tb) do
		tb[k]= nil
	end
end

function cleanTable(s)
	for k,v in pairs(s) do
		s[k] = nil
	end
end

function getBit(n, index)
	local div = 2 ^ index
	return (n - n % div) / div % 2
end

function setBit(n, index)
	local bit = getBit(n, index)
	if bit ~= 0 then
		assert()
	end
	return n + 2 ^ index
end

function hypot(a, b)
	return math.sqrt(a * a + b * b)
end

local out = {}
local out_len = 0
function printTable(tb, step)
	if not step then
		step = 0
		out_len = 0
	end
	for k, v in pairs(tb) do
		for i = 1, step do
			out_len = out_len + 1
			out[out_len] = "	"
		end

		if type(k) == "number" then
			out_len = out_len + 1
			out[out_len] = "["
		end

		out_len = out_len + 1
		out[out_len] = k

		if type(k) == "number" then
			out_len = out_len + 1
			out[out_len] = "]"
		end

		out_len = out_len + 1
		out[out_len] = "="

		if type(v) == "string" then
			out_len = out_len + 1
			out[out_len] = "\""
		end

		out_len = out_len + 1
		out[out_len] = type(v) == "table" and "" or v
		if type(v) == "boolean" then
			out[out_len] = tostring(v)
		end

		if type(v) == "string" then
			out_len = out_len + 1
			out[out_len] = "\""
		end

		out_len = out_len + 1
		out[out_len] = "\n"

		if type(v) == "table" then
			printTable(v, step + 1)
		end
	end
	if step == 0 then
		local str = table.concat(out, nil, 1, out_len)
        print(str)
		return str
	end
end

-- 判断是否同一天
function isSameDay(time1)
	if not time1 then
		return
	end
	local now = os.time()
	local tToday = os.date("%Y%m%d", now)
	local t1 = os.date("%Y%m%d", time1)
	if tToday ~= t1 then
		return
	end
	return now
end

-- 判断传入的两个时间是否同一天
function isSameDayByTimes(time1,time2)
	if not time1 or not time2 then
		return
	end
	local t1 = os.date("%Y%m%d", time1)
	local t2 = os.date("%Y%m%d", time2)
	if t1 ~= t2 then
		return
	end
	return true
end

-- 是否同一个月
function isSameMonth(time)
	local now = os.date("*t")
	local d = os.date("*t",time)	
	return now.year==d.year and now.month==d.month
end

-- 判断传入时间点与当前时间相差多少天
local tb = {}
function diffDay(time)
	local d = os.date("*t",time)
	tb.year = d.year
	tb.month = d.month
	tb.day = d.day
	time = os.time(tb)
	local nowDay = os.date("*t")
	tb.year = nowDay.year
	tb.month = nowDay.month
	tb.day = nowDay.day
	local nowTime = os.time(tb)
	return math.ceil(math.abs(nowTime-time)/86400)
end

-- 判断传入时间点与当前时间相差多少小时
function diffHour(time)
	local d = os.date("*t",time)
	tb.year = d.year
	tb.month = d.month
	tb.day = d.day
	time = os.time(tb)
	local nowDay = os.date("*t")
	tb.year = nowDay.year
	tb.month = nowDay.month
	tb.day = nowDay.day
	local nowTime = os.time(tb)
	return math.ceil(math.abs(nowTime-time)/3600)
end

function diffDayByTimes(time1,time2)
	local t1 = os.date("*t",time1)
	tb.year = t1.year
	tb.month = t1.month
	tb.day = t1.day
	time1 = os.time(tb)
	local t2 = os.date("*t",time2)
	tb.year = t2.year
	tb.month = t2.month
	tb.day = t2.day
	time2 = os.time(tb)
	return math.ceil(math.abs(time1-time2)/86400)
end

-- 获取本月有多少天
function getMonthDayNum()
	local currMonthDate = os.date("*t")
	tb.year = currMonthDate.year
	tb.month = currMonthDate.month
	tb.day = currMonthDate.day
	currMonthDate.hour = nil 
	currMonthDate.min = nil
	currMonthDate.sec = nil
	currMonthDate.day = 1
	tb.day = 1
	
	if tb.month<12 then	
		tb.month = tb.month + 1
	else
		tb.year = tb.year+1 
		tb.month = 1
	end
	
	local nextMonthFirstDayTime = os.time(tb)
	local currMonthTime = os.time(currMonthDate)
	
	return math.floor(math.abs(nextMonthFirstDayTime-currMonthTime)/86400)
end

-- 取时间间隔 s
function getInterval(time)
	if not time then
		return math.huge
	end
	local now = os.time()
	return now - time
end

--参数结构：year=****,month=****,day=****
function isTime( startDate, endDate)
	local date_min = os.time(startDate) - 12 * 60 * 60
	local date_max = os.time(endDate) + 12 * 60 * 60
	local tmp_time = os.time()
	if not (date_min <= tmp_time and tmp_time < date_max) then
		return false
	end
	return true, date_max - tmp_time
end

-- check time
function checkTime(startTimeConf,endTimeConf)
	local nowDate = os.date("*t")
	local nowMin = nowDate.hour * 60 + nowDate.min
	
	local startMin = startTimeConf.hour * 60 + startTimeConf.min 
	local endMin = endTimeConf.hour * 60 + endTimeConf.min
	
	if nowMin >= startMin and nowMin < endMin then
		return true
	end 
end



-- 检查传入时间，是否经过resetTime时间点;
function isTimeOver(time,resetTime)
	
	if not time or not resetTime then
		return
	end
	
	local nowTime = os.time()
	local nowDay = os.date("%d", nowTime) + 0
	local nowHour = os.date("%H", nowTime) + 0
	
	local getDay = os.date("%d", time) + 0
	local getHour = os.date("%H", time) + 0
	
	local dirty = false
	if nowDay == getDay then
		if getHour < resetTime and nowHour >= resetTime then
			dirty = true
		end
	elseif nowDay == getDay + 1 then
		if nowHour >= resetTime then
			dirty = true	
		end
	else
		dirty = true
	end
	return dirty
end

tmpDate = tmpDate or {}
-- 取本月开始时间
function getMonthStartTime(time)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.day = 1
	tmpDate.hour = 0
	tmpDate.min = 0
	tmpDate.sec = 0
	return os.time(tmpDate)
end

-- 取本周开始时间 周一凌晨
function getWeekStartTime(time)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.hour = 0
	tmpDate.min = 0
	tmpDate.sec = 0
	local day = nil
	if d.wday == 1 then
		day = 6
	else
		day = d.wday - 2
	end
	tmpDate.day = d.day - day
	return os.time(tmpDate)
end

-- 取本日开始时间
function getDayStartTime(time)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.day = d.day
	tmpDate.hour = 0
	tmpDate.min = 0
	tmpDate.sec = 0
	return os.time(tmpDate)
end

-- 取相差几天时间
function getNextDayTime(time, day)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.day = d.day
	tmpDate.hour = 0
	tmpDate.min = 0
	tmpDate.sec = 0
	local ts = os.time(tmpDate)
	local dayTs = day * 86400
	return ts + dayTs
end

-- 获取前几天数据
function getLastDayTime(time, day)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.day = d.day
	tmpDate.hour = 0
	tmpDate.min = 0
	tmpDate.sec = 0
	local ts = os.time(tmpDate)
	local dayTs = day * 86400
	return ts - dayTs
end

-- 取本日特定小时时间戳
function getDayHourTime(time, hour)
	local d = os.date("*t",time)
	tmpDate.year = d.year
	tmpDate.month = d.month
	tmpDate.day = d.day
	tmpDate.hour = hour
	tmpDate.min = 0
	tmpDate.sec = 0
	return os.time(tmpDate)
end

-- 判断传入时间点，是否同周
function isSameWeek(time1,time2)
	if not time1 or not time2 then
		return
	end
	return getWeekStartTime(time1) == getWeekStartTime(time2)
end

-- 星期中第几天的数字表示 1（表示星期天）到 7（表示星期六） 
function getWeekDay( time )
	local time = time or os.time()
	local d = os.date("*t",time)
	return d.wday
end

function split(str, split_char,isNumber)
    local t = {}
    while string.len(str)>0 do
        local pos = string.find(str, split_char);
        if (not pos) then
        	if isNumber then
            	t[#t + 1] = tonumber(str) or 0
            else
            	t[#t + 1] = str
            end
            break
        end
        local sub_str = string.sub(str, 1, pos - 1)
    	if isNumber then
        	t[#t + 1] = tonumber(sub_str) or 0
        else
        	t[#t + 1] = sub_str
        end
        str = string.sub(str, pos + 1, #str)
    end
    return t
end

-- 根据KEY从小到大排序
function pairsByKeys(t)
	local a = {}
	for n in pairs(t) do
		a[#a+1] = n
	end
	table.sort(a)
	local i = 0
	return function()
	i = i + 1
	return a[i], t[a[i]]
	end
end 

function cmptb(a, b)
	for k, v in pairs(a) do
		if type(v) == "table" then
			if type(b[k]) ~= "table" then
				return
			end
			if not cmptb(v, b[k]) then
				return
			end
		else
			if b[k] ~= v and k ~= "now" and k ~= "uid" then
				return
			end
		end
	end
	for k, v in pairs(b) do
		if type(v) == "table" then
			if type(a[k]) ~= "table" then
				return
			end
			if not cmptb(v, a[k]) then
				return
			end
		else
			if a[k] ~= v and k ~= "now" and k ~= "uid" then
				return
			end
		end
	end
	return true
end

function getWay(dx, dy)
	return ((floor(( atan2(dy, dx) + 11.388) / 1.57)) % 4) * 2;
end

function tableIsEmpty(tb)
	return _G.next(tb) == nil
end

-- 服务器是否符合
function checkSvrIndex(svrIndexs, svrIndex)
	if #svrIndexs < 1 then return true end

	if not svrIndex then
		svrIndex = Config.SVR_INDEX
	end

	for i = 1, #svrIndexs do
		if svrIndexs[i][1] <= svrIndex and 
			svrIndex <= svrIndexs[i][2] then
			return true
		end
	end
end

-- 含中文文本长度
function utf8len(content)
    local len = string.len(content)
    local left = len
    local cnt = 0
    local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
    while left ~= 0 do
        local tmp = string.byte(content, -left)
        local i = #arr
        while arr[i] do
            if tmp >= arr[i] then
                left = left - i
                break
            end
            i = i - 1
        end
        cnt = cnt + 1
    end
    return cnt
end

function checkRandom(cmpValue)
	local r = math.random(0,10000)
	if r < cmpValue then
		return true
	end
end

SEPARATOR = "||"
function format(...)
	local str = ""
	local t = {}
	for k,v in ipairs({...}) do
		if k == 1 then
			str = str .. v
		else
			t = split(v, SEPARATOR)
			if #t > 1 then
				t[1] = string.gsub(t[1],"({(.-)})",function(p1,p2)
					p2 = tonumber(p2)
					if p2 and t[p2+1] then
						return string.sub(t[p2+1], 2)
					else
						return p1
					end
				end)
			end
            if t[1] then
			   str = str .. SEPARATOR .. t[1]
            end
		end
	end
	return str
end